/* The file is part of the Waff web framework.
 *
 * Copyright (c) 2011, Grzegorz Skorupa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditionsare met:
 *
 * - Redistributions of source code must retain the above copyright notice, this list of conditions
 *   and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions
 *   and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * - Neither the name of the Grzegorz Skorupa nor the names of its contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package pl.org.waff.repository;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;
import pl.org.waff.GuidGenerator;

/**
 *
 * @author greg
 */
public class InMemoryContentCache implements ContentCache {

    private HashMap documents;
    private HashMap comments;
    private HashMap documentComments;
    private HashMap folders;
    private HashMap folderTypes;
    private HashMap types;
    private HashMap trash;
    private static final Logger log = Logger.getLogger(InMemoryContentCache.class.getName());

    public void init() {
        documents = new HashMap();
        comments = new HashMap();
        documentComments = new HashMap();
        folders = new HashMap();
        folderTypes = new HashMap();
        types = new HashMap();
        trash = new HashMap();

        addFolder("/");
        addType("article");
        addType("image");
        addType("map");
        addType("video");
        addType("file");
        //log.info("adding document to the repository. result == " + putDocument("/", doc));
    }

    public void addFolder(String folderPath) {
        if (folderPath == null) {
            return;
        }
        if (!folderPath.startsWith("/")) {
            folderPath = "/" + folderPath;
        }
        if (folders.containsKey(folderPath)) {
            return;
        }
        folders.put(folderPath, new ArrayList());
    }

    public void addType(String typeName) {
        if (typeName == null) {
            return;
        }
        types.put(typeName, "");
    }

    public Document getDocument(String id) {
        return (Document) documents.get(id);
    }

    public Comment getComment(String id) {
        return (Comment) comments.get(id);
    }

    public ArrayList findDocuments(String folderPath, 
            String documentType, 
            String status, 
            String target) {
        return findDocuments(folderPath, documentType, status, target, null);
    }
    //TODO: status and target
    public ArrayList findDocuments(String folderPath, String documentType, String status, String target, String tag) {
        ArrayList ids = new ArrayList();
        if (documentType == null) {
            if (folderPath != null) {
                if (folders.containsKey(folderPath)) {
                    ids = (ArrayList) folders.get(folderPath);
                }
            } else {
                //TODO: find all documents of type
            }
        } else {
            if (folderTypes != null && folderPath != null && folderPath.length() > 0) {
                log.fine("" + folderTypes.size());
                log.fine(folderTypes.toString());
                if (folderTypes.containsKey(documentType + ":" + folderPath)) {
                    ids = (ArrayList) folderTypes.get(documentType + ":" + folderPath);
                }
            } else if (folderPath == null) {
                //TODO: find all documents of type
            }
        }
        Collections.sort(ids, new PublishedComparator());
        return ids;
    }

    //TODO: findComments
    public ArrayList findComments(String documentId, String status) {
        ArrayList ids;
        ids = (ArrayList) documentComments.get(documentId);
        if (ids == null) {
            ids = new ArrayList();
        } else {
            //filter statuses
        }
        return ids;
    }

    //TODO: getCommentsInfo
    public Properties getCommentsInfo(String documentId) {
        Properties properties = new Properties();
        if (documentId != null) {
            properties.setProperty("document.id", documentId);
            List list = findComments(documentId, null);
            properties.setProperty("counter", "" + list.size());
        } else {
            properties.setProperty("counter", "" + comments.size());
        }

        properties.setProperty("created", "2011-12-31 23:59");
        return properties;
    }

    //TODO:: findDocuments - queryString
    public ArrayList findDocuments(String folderPath, String documentType, String queryString) {
        ArrayList ids = new ArrayList();
        return ids;
    }

    public List getAllFolders() {
        ArrayList folderPaths = new ArrayList();
        Iterator it = folders.keySet().iterator();
        while (it.hasNext()) {
            folderPaths.add((String) it.next());
        }
        return folderPaths;
    }

    public List getAllTypes() {
        ArrayList typeNames = new ArrayList();
        Iterator it = types.keySet().iterator();
        while (it.hasNext()) {
            typeNames.add((String) it.next());
        }
        return typeNames;
    }

    public ArrayList getSubfolders(String parentPath) {
        Iterator it = folders.keySet().iterator();
        ArrayList subfolders = new ArrayList();
        String key;
        while (it.hasNext()) {
            key = (String) it.next();
            if (key.startsWith(parentPath)) {
                if ("/".equals(parentPath) && key.lastIndexOf("/") == 0) {
                    subfolders.add(key);
                } else if (key.lastIndexOf("/") == parentPath.length()) {
                    subfolders.add(key);
                }
            }
        }
        return subfolders;
    }

    public int putDocument(String folderPath, Document document) {
        if (document == null) {
            return ERR_DOCUMENT_IS_NULL;
        }
        if (folderPath == null || folderPath.isEmpty()) {
            return ERR_PATH_IS_EMPTY;
        }
        if (document.getType() == null) {
            return ERR_TYPE_IS_NULL;
        }

        if ("new".equals(document.getId()) || "-1".equals(document.getId())) {
            document.setId(GuidGenerator.getGuid("doc"));
        }

        if (document.getTitle() == null || document.getTitle().isEmpty()) {
            document.setTitle(document.getId());
        }
        //TODO: synchronization
        String typedPathKey = document.getType() + ":" + folderPath;
        ArrayList folderElements;
        ArrayList folderTypedElements;
        folderElements = (ArrayList) folders.get(folderPath);
        if (folderElements == null) {
            folderElements = new ArrayList();
        }
        folderTypedElements = (ArrayList) folderTypes.get(typedPathKey);
        if (folderTypedElements == null) {
            folderTypedElements = new ArrayList();
        }

        int index = folderElements.indexOf(document.getId());
        if (index >= 0) {
            folderElements.set(index, document.getId());
        } else {
            folderElements.add(document.getId());
        }

        index = folderTypedElements.indexOf(document.getId());
        if (index >= 0) {
            folderTypedElements.set(index, document.getId());
        } else {
            folderTypedElements.add(document.getId());
        }
        // store new arrays
        folders.put(folderPath, folderElements);
        folderTypes.put(typedPathKey, folderTypedElements);
        documents.put(document.getId(), document);
        types.put(document.getType(), "");
        return ERR_NO_ERROR;
    }

    public int putComment(Comment comment) {
        if ("new".equals(comment.getId()) || "-1".equals(comment.getId())) {
            comment.setId(GuidGenerator.getGuid("com"));
        }
        if (comment.getTitle() == null || comment.getTitle().isEmpty()) {
            comment.setTitle("...");
        }
        comments.put(comment.getId(), comment);
        ArrayList list;
        list = (ArrayList) documentComments.get(comment.getParent());
        if (list == null) {
            list = new ArrayList();
        }
        int index;
        index = list.indexOf(comment.getId());
        if (index > -1) {
            list.set(index, comment.getId());
        } else {
            list.add(comment.getId());
        }
        documentComments.put(comment.getParent(), list);
        return ERR_NOT_IMPLEMENTED;
    }

    public int trashDocument(String id) {
        return ERR_NOT_IMPLEMENTED;
    }

    public int deleteDocument(String id) {
        trash.remove(id);
        return ERR_NO_ERROR;
    }

    //TODO: deleteComment
    public int deleteComment(String id) {
        return ERR_NOT_IMPLEMENTED;
    }

    //TODO: deleteFolder
    public int deleteFolder(String path) {
        return ERR_NOT_IMPLEMENTED;
    }
}
